REBUILD INDEX可以減少Fragmentation所帶來的影響,REBUILD INDEX後碎裂程度變小,查詢的邏輯讀取與花費時間也跟著變小,讓效能上升。
上一篇淺談Imdex與Fragmentation文中提到REBUILD INDEX可以減少Fragmentation所帶來的影響,不過凡事必須有憑有據才可以說服他人,這篇我就實作REBUILD INDEX前後查詢資料的差異(我總共做了五次)。
建立測試的Table與Index
IF OBJECT_ID('TestFregmenationTable') IS NOT NULL
BEGIN
DROP TABLE TestFregmenationTable
END
GO
--建立測試的Table
CREATE TABLE TestFregmenationTable
(
COLUMN1 INT ,
Data CHAR(2000)
)
GO
--建立叢集索引
CREATE CLUSTERED INDEX [IX_Index] ON [dbo].[TestFregmenationTable] (COLUMN1)
GO
建立測試資料(要執行兩次) 並看碎裂程度
--建立測試資料
DECLARE @i INT
SET @i = 1
WHILE @i <= 1000
BEGIN
INSERT INTO dbo.TestFregmenationTable VALUES(@i,'RYO')
SET @i = @i + 1
END
GO
--查看INDEX的碎裂程度
SELECT DB_NAME() DBName,i.name AS IndexName
, ROUND(s.avg_fragmentation_in_percent,2) AS [FragmentationPercentage]
FROM sys.dm_db_index_physical_stats(DB_ID('Performance'),NULL, NULL, NULL, NULL) s
INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id]
AND s.index_id = i.index_id
WHERE i.name='IX_Index'
ORDER BY 3 DESC
GO
查詢結果並觀察效能
--執行查詢
SELECT * FROM dbo.TestFregmenationTable
WHERE COLUMN1 BETWEEN 25 AND 29
在REBUILD INDEX之前,碎裂程度是66.7,而執行結果邏輯讀取為10,花費時間80 ms
REBUILD INDEX並看碎裂程度
--重建INDEX
ALTER INDEX [IX_Index] ON [dbo].[TestFregmenationTable] REBUILD
GO
--查看INDEX的碎裂程度
SELECT DB_NAME() DBName,i.name AS IndexName
, ROUND(s.avg_fragmentation_in_percent,2) AS [FragmentationPercentage]
FROM sys.dm_db_index_physical_stats(DB_ID('Performance'),NULL, NULL, NULL, NULL) s
INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id]
AND s.index_id = i.index_id
WHERE i.name='IX_Index'
ORDER BY 3 DESC
GO
再次查詢結果並觀察效能
--清除CACHE
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
--再次執行查詢
SELECT * FROM dbo.TestFregmenationTable
WHERE COLUMN1 BETWEEN 25 AND 29
在REBUILD INDEX之後,碎裂程度是0,而執行結果邏輯讀取為6,花費時間63 ms
附註:邏輯讀取是查詢時從DATA CACHE讀取PAGE的次數,邏輯讀取越小越好。
結論:我們發現REBUILD INDEX後碎裂程度變小,查詢的邏輯讀取與花費時間也跟著變小,原因是因為REBUILD INDEX時把散落不同PAGE的DATA重新集中,所以查詢資料時就所讀的PAGE變少,效能也跟著上升。